package jp.co.nes.awssupport.common.utility;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.elasticache.AmazonElastiCache;
import com.amazonaws.services.elasticache.AmazonElastiCacheClientBuilder;
import com.amazonaws.services.elasticache.model.DescribeReservedCacheNodesRequest;
import com.amazonaws.services.elasticache.model.DescribeReservedCacheNodesResult;
import com.amazonaws.services.elasticache.model.ReservedCacheNode;
import com.amazonaws.services.elasticache.model.ReservedCacheNodeNotFoundException;

import jp.co.nes.awssupport.common.base.CommonException;

/**
 * ElastiCacheヘルパーです。<br>
 * ElastiCacheに関する機能を提供します。
 */
public class AwsElastiCacheHelper extends AwsHelperBase {

    /** クライアント */
    private AmazonElastiCache client;

    /**
     * デフォルトコンストラクタです。
     */
    public AwsElastiCacheHelper() {
    }

    /**
     * リージョンを引数にもつコンストラクタです。
     *
     * @param regions リージョン
     * @param accessKey アクセスキー
     * @param secretKey シークレットキー
     */
    public AwsElastiCacheHelper(Regions regions, String accessKey, String secretKey) {
        super(regions, accessKey, secretKey);
    }

    /*
     * (非 Javadoc)
     * @see jp.co.nes.awssupport.common.utility.AwsHelperBase#init(com.amazonaws.regions.Regions, com.amazonaws.auth.AWSCredentials, com.amazonaws.ClientConfiguration)
     */
    @Override
    protected void init(Regions regions, AWSCredentials credentials, ClientConfiguration config) {
        boolean isLocalTest = Boolean.valueOf(PropertiesUtil.getProperty("LocalTest", "false"));
        if (!isLocalTest) {
            if (credentials == null) {
                if (config == null) {
                    client = AmazonElastiCacheClientBuilder.standard()
                            .withRegion(regions)
                            .build();
                } else {
                    client = AmazonElastiCacheClientBuilder.standard()
                            .withRegion(regions)
                            .withClientConfiguration(config)
                            .build();
                }
            } else {
                if (config == null) {
                    client = AmazonElastiCacheClientBuilder.standard()
                            .withRegion(regions)
                            .withCredentials(new AWSStaticCredentialsProvider(credentials))
                            .withClientConfiguration(new ClientConfiguration())
                            .build();
                } else {
                    client = AmazonElastiCacheClientBuilder.standard()
                            .withRegion(regions)
                            .withCredentials(new AWSStaticCredentialsProvider(credentials))
                            .withClientConfiguration(config)
                            .build();
                }
            }
        }
    }

    /**
     * ReservedCacheNodeリストを含むマップ(キー=リージョン)を返却します。<br>
     * リージョン内に、ReservedCacheNodeがない場合、空リストがマップに登録されます。<br>
     * なお、検索するリージョンは、{@link AwsValidRegions#getRegions()}で返却されたリージョンになります。
     *
     * @return ReservedCacheNodeリストを含むマップ(キー=リージョン)
     */
    @Deprecated
    public static Map<Regions, List<ReservedCacheNode>> describeReservedCacheNodes(String accessKey, String secretKey) {
        Map<Regions, List<ReservedCacheNode>> reservedCacheNodeListMap = new HashMap<>();
        List<Regions> validRegionsList = AwsValidRegions.getRegions();
        for (Regions regions : validRegionsList) {
            AwsElastiCacheHelper helper = new AwsElastiCacheHelper(regions, accessKey, secretKey);
            DescribeReservedCacheNodesResult result = helper.describeReservedCacheNodes();
            reservedCacheNodeListMap.put(regions, result.getReservedCacheNodes());
        }
        return reservedCacheNodeListMap;
    }

    /**
     * ReservedCacheNodeを返却します。
     *
     * @return ReservedCacheNode
     */
    @Deprecated
    public DescribeReservedCacheNodesResult describeReservedCacheNodes() {
        DescribeReservedCacheNodesRequest request = new DescribeReservedCacheNodesRequest();
        return client.describeReservedCacheNodes(request);
    }

    /**
     * ReservedCacheNodeを返却します。<br>
     * reservedCacheNodeIdに対応するReservedCacheNodeがなかった場合はnullを返却します。
     *
     * @param reservedCacheNodeId reservedCacheNodeId
     * @return ReservedCacheNode
     */
    public ReservedCacheNode getReservedCacheNode(String reservedCacheNodeId) {
        DescribeReservedCacheNodesRequest request = new DescribeReservedCacheNodesRequest();
        request.setReservedCacheNodeId(reservedCacheNodeId);
        DescribeReservedCacheNodesResult result = null;
        try {
            result = client.describeReservedCacheNodes(request);
        } catch (ReservedCacheNodeNotFoundException e) {
            // 存在しなかった場合、何もせず、処理を続行する。
        }

        ReservedCacheNode reservedCacheNode = null;
        if (result != null && result.getReservedCacheNodes() != null) {
            List<ReservedCacheNode> reservedCacheNodeList = result.getReservedCacheNodes();
            int size = reservedCacheNodeList.size();
            if (size == 1) {
                reservedCacheNode = reservedCacheNodeList.get(0);
            } else if (size > 1) {
                throw new CommonException("size > 1(size=" + size + ")");
            }
        }
        return reservedCacheNode;
    }
}
